package com.wm.blog_common.util;

import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: 半卷流年
 * @date: 2020/04/01
 * @description: String工具类
 */
public class StringUtil {

    private static Pattern commonExp = Pattern.compile("(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)");
    private static Pattern mobileExp = Pattern.compile("^(13[0-9]|14[5-9]|15[0|1|2|3|5|6|7|8|9]|16[0-9]|18[0-9]|17[0|1|3|5|6|7|8]|199|191|198|166)\\d{8}$");
    private static Pattern dateExp = Pattern.compile("(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)");

    /**
     * 身份证正则18位
     */
    private final static String IDENTITY_CARD_18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}(\\d|[xX])$";
    /**
     * 身份证正则15位
     */
    private final static String IDENTITY_CARD_15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$";


    /**
     * 隐藏构造方法
     */
    private StringUtil() {

    }

    /**
     * 连接数组
     *
     * @param arr
     * @param type
     * @return
     */
    public static String joinArr(Object[] arr, String type) {
        if (arr == null) {
            return "";
        }
        StringBuilder tmp = new StringBuilder();
        int i = 0;
        for (Object o : arr) {
            String s = String.valueOf(o);
            if (i > 0) {
                tmp.append(type);
            }
            tmp.append(s);
            i++;
        }
        return tmp.toString();
    }

    /**
     * 是否为空
     * 与common-lang的区别：“null”字符串也会返回true
     *
     * @param str 字符串
     * @return 是否为空
     */
    public static boolean isEmpty(String str) {
        return str == null || "null".equals(str) || str.length() == 0;
    }

    /**
     * 是否不为空
     *
     * @param str 字符串
     * @return 是否不为空
     */
    public static boolean isNotEmpty(String str) {
        boolean notNullBol =!"NULL".equalsIgnoreCase(str);
        return str != null && str.length() > 0  && notNullBol;

    }

    /**
     * 截取字符串
     *
     * @param source
     * @param start
     * @param end
     * @return
     */
    public static String findStr(String source, String start, String end) {
        if (source == null) {
            return null;
        }
        int i;
        if (!isEmpty(start)) {
            i = source.indexOf(start);
            if (i < 0) {
                return null;
            }
            source = source.substring(i + start.length());
        }
        if (!isEmpty(end)) {
            i = source.indexOf(end);
            if (i < 0) {
                return null;
            }
            source = source.substring(0, i);
        }
        return source;
    }

    /**
     * 用0补全数值
     *
     * @param index
     * @param length
     * @return
     */
    public static String getIndexString(int index, int length) {
        String sDatesBefor = String.valueOf(index);
        while (sDatesBefor.length() < length) {
            sDatesBefor = "0" + sDatesBefor;
        }
        return sDatesBefor;
    }

    public static boolean isBlank(String str) {
        int strLen;
        if (str != null && (strLen = str.length()) != 0) {
            for (int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(str.charAt(i))) {
                    return false;
                }
            }
        }
        return true;
    }

    public static String lowerFirst(String str) {
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }

    public static String upperFirst(String str) {
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    public static <T> T castObjectToClazz(Class<T> clazz, String str) {
        T result = null;
        if (clazz.equals(Integer.class) && StringUtils.isNotEmpty(str)) {
            result = (T) new Integer(str);
        } else if (clazz.equals(String.class) && StringUtils.isNotEmpty(str)) {
            result = (T) str;
        } else if (clazz.equals(Double.class) && StringUtils.isNotEmpty(str)) {
            result = (T) new Double(str);
        } else if (clazz.equals(Boolean.class) && StringUtils.isNotEmpty(str)) {
            result = (T) new Boolean(str);
        }
        return result;
    }

    public static String buildUUID() {
        return UUID.randomUUID().toString().replaceAll("\\-", "");
    }

    public static boolean checkMobile(String mobileNumber) {
        if(mobileNumber.length() != 11) {
            return false;
        }
        if("142".equals(mobileNumber.substring(0, 3))) {
            return true;
        }
        Matcher matcher = mobileExp.matcher(mobileNumber);
        return matcher.matches();
    }

    /**
     *  根据身份证获取年龄，性别
     * 2表示女
     * 1表示男
     * @param idNum
     * @return
     * String[]
     */
    public static String[] getAgeAndSexById(String idNum) {
        String age = "";
        String sex = "";
        GregorianCalendar calendar = new GregorianCalendar(TimeZone.getDefault());
        int currentYear = calendar.get(Calendar.YEAR);
        if (idNum.matches("^\\d{15}$|^\\d{17}[\\dxX]$")) {
            if (idNum.length() == 18) {
                Pattern pattern = Pattern.compile("\\d{6}(\\d{4})\\d{6}(\\d{1})[\\dxX]{1}");
                Matcher matcher = pattern.matcher(idNum);
                if (matcher.matches()) {

                    age = String.valueOf(currentYear - Integer.parseInt(matcher.group(1)));
                    sex = "" + Integer.parseInt(matcher.group(2))%2;
                }
            } else if (idNum.length() == 15) {
                Pattern p = Pattern.compile("\\d{6}(\\d{2})\\d{5}(\\d{1})\\d{1}");
                Matcher m = p.matcher(idNum);
                if (m.matches()) {
                    int year = Integer.parseInt(m.group(1));
                    year = 2000 + year;
                    if (year > 2020) {
                        year = year - 100;
                    }
                    age = String.valueOf(currentYear - year);
                    sex = "" + Integer.parseInt(m.group(2))%2;
                }
            }
        }
        if ("0".equals(sex)) {
            sex = "2";
        }
        return new String[]{age, sex};
    }

    public static int getGenderByIdCard(String idCardNo){
        String dates = idCardNo.substring(6, 14);
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
        String year=df.format(new Date());
        int u=Integer.parseInt(year)-Integer.parseInt(dates);
        return u/10000;

    }

    /**
     * 检查身份证号码合法性
     * @param idCardNo
     * @return
     * @throws Exception
     */
    public static boolean checkIdCardNo(String idCardNo) {
        try {
            if(StringUtils.isBlank(idCardNo)){
                return false;
            }
            int length = idCardNo.length();
            if(length == 15){
                Pattern p = Pattern.compile("^[0-9]*$");
                Matcher m = p.matcher(idCardNo);
                if (m.matches()) {
                    int year = Integer.parseInt(idCardNo.substring(6, 8));
                    year = 2000 + year;
                    if (year > 2020) {
                        year = year - 100;
                    }
                    String dateStr = year + "-" + idCardNo.substring(8, 10) + "-" + idCardNo.substring(10, 12);
                    Matcher dateMatcher = dateExp.matcher(dateStr);
                    return dateMatcher.matches();
                } else {
                    return false;
                }
            }else if(length == 18){
                String front_17 = idCardNo.substring(0, idCardNo.length() - 1);//号码前17位
                String verify = idCardNo.substring(17, 18);//校验位(最后一位)
                Pattern p = Pattern.compile("^[0-9]*$");
                Matcher m = p.matcher(front_17);
                if(!m.matches()){
                    return false;
                }else{
                    String dateStr = idCardNo.substring(6, 10) + "-" + idCardNo.substring(10, 12) + "-" + idCardNo.substring(12, 14);
                    Matcher dateMatcher = dateExp.matcher(dateStr);
                    if (dateMatcher.matches()) {
                        return checkVerify(front_17, verify);
                    } else {
                        return false;
                    }
                }
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 校验验证位合法性
     * @param front_17
     * @param verify
     * @return
     * @throws Exception
     */
    public static boolean checkVerify(String front_17,String verify) throws Exception{
        try {
            int[] wi = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1};
            String[] vi = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
            int s = 0;
            for(int i = 0; i<front_17.length(); i++){
                int ai = Integer.parseInt(front_17.charAt(i) + "");
                s += wi[i]*ai;
            }
            int y = s % 11;
            String v = vi[y];
            if(!(verify.toUpperCase().equals(v))){
                return false;
            }
            return true;
        } catch (Exception e) {
            throw e;
        }
    }


    /**
     * 校验身份证是否合法
     * @param identity
     * @return
     */
    public static Boolean checkIdentityCard(String identity){
        Boolean isOk = false;
        if(StringUtil.isNotEmpty(identity)){
            identity = identity.trim();
            if(identity.length() == 15){
                isOk = RegexUitl.check(identity,IDENTITY_CARD_15);
            }
            if(identity.length() == 18){
                isOk = RegexUitl.check(identity,IDENTITY_CARD_18);
            }
        }
        return isOk;
    }


    /**
     * 字符串转换成为16进制(无需Unicode编码)
     * @param str
     * @return
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString();
    }



    /**
     * 16进制直接转换成为字符串(无需Unicode解码)
     * @param hexStr
     * @return
     */
    public static String hexStr2Str(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        return new String(bytes);
    }

    public static String toStr(Object obj) {
        return obj == null ? null : String.valueOf(obj);
    }

}
